using MediatR;
using SqlSugar;

namespace Service.Repository
{
    public interface IEntityTenant
    {

        /// <summary>
        /// 租户id
        /// </summary>
        string TenantId { get; }
    }



    public class Entity : IEntity
    {
        public Entity()
        {
        }
        List<INotification> _domainEvents;


        [SugarColumn(IsIgnore = true)]
        public IReadOnlyCollection<INotification> DomainEvents => _domainEvents?.AsReadOnly();


        // public async Task PushDomainEvent(IMediator mediator)
        // {
        //     foreach (var notification in _domainEvents)
        //     {
        //         await mediator.Publish(notification);
        //     }
        //     ClearDomainEvents();
        // }

        public void AddDomainEvent(INotification eventItem)
        {
            _domainEvents = _domainEvents ?? new List<INotification>();
            _domainEvents.Add(eventItem);
        }

        public void RemoveDomainEvent(INotification eventItem)
        {
            _domainEvents?.Remove(eventItem);
        }

        public void ClearDomainEvents()
        {
            _domainEvents?.Clear();
        }
    }

    public class Entity<TKey> : Entity, IEntity<TKey>
    {
        int? _requestedHashCode;
        TKey _id;
        DateTime _createTime;
        DateTime? _updateTime;
        DateTime? _deleteTime;
        bool _isDelete;
        long _createById;
        long? _deleteById;
        long? _updateById;
        /// <summary>
        /// 添加默认函数
        /// </summary>
        public Entity()
        {
        }

        [SugarColumn(ColumnName = "id", IsPrimaryKey = true)]
        public virtual TKey Id { get { return _id; } protected set { _id = value; } }


        [SugarColumn(ColumnName = "create_time", IsOnlyIgnoreUpdate = true)]
        public DateTime CreateTime { get { return _createTime; } protected set { _createTime = value; } }


        [SugarColumn(ColumnName = "update_time", IsOnlyIgnoreInsert = true)]
        public DateTime? UpdateTime { get { return _updateTime; } protected set { _updateTime = value; } }

        [SugarColumn(ColumnName = "delete_time", IsOnlyIgnoreInsert = true)]
        public DateTime? DeleteTime { get { return _deleteTime; } protected set { _deleteTime = value; } }

        [SugarColumn(ColumnName = "is_delete")]
        public bool IsDelete { get { return _isDelete; } set { _isDelete = value; } }

        [SugarColumn(ColumnName = "create_id", IsOnlyIgnoreUpdate = true)]
        public long CreateById { get { return _createById; } protected set { _createById = value; } }

        [SugarColumn(ColumnName = "delete_id", IsOnlyIgnoreInsert = true)]
        public long? DeleteById { get { return _deleteById; } protected set { _deleteById = value; } }

        [SugarColumn(ColumnName = "update_id", IsOnlyIgnoreInsert = true)]
        public long? UpdateById { get { return _updateById; } protected set { _updateById = value; } }

        public void Delete()
        {
            IsDelete = true;
        }






        public override bool Equals(object obj)
        {
            if (obj == null || !(obj is Entity<TKey>))
                return false;

            if (Object.ReferenceEquals(this, obj))
                return true;

            if (this.GetType() != obj.GetType())
                return false;

            Entity<TKey> item = (Entity<TKey>)obj;

            if (item.IsTransient() || this.IsTransient())
                return false;
            else
                return item.Id.Equals(this.Id);
        }


        public override int GetHashCode()
        {
            if (!IsTransient())
            {
                if (!_requestedHashCode.HasValue)
                    _requestedHashCode = this.Id.GetHashCode() ^ 31;

                return _requestedHashCode.Value;
            }
            else
                return base.GetHashCode();
        }


        //表示对象是否为全新创建的，未持久化的
        public bool IsTransient()
        {
            return EqualityComparer<TKey>.Default.Equals(Id, default);
        }

        public override string ToString()
        {
            return $"[Entity: {GetType().Name}] Id = {Id}";
        }


        public static bool operator ==(Entity<TKey> left, Entity<TKey> right)
        {
            if (Object.Equals(left, null))
                return (Object.Equals(right, null)) ? true : false;
            else
                return left.Equals(right);
        }

        public static bool operator !=(Entity<TKey> left, Entity<TKey> right)
        {
            return !(left == right);
        }
    }
}